package com.zhangc.blog.admin.web.controller.admin;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhangc.blog.admin.entity.BlogCategoryEntity;
import com.zhangc.blog.admin.entity.BlogCommentEntity;
import com.zhangc.blog.admin.entity.BlogConfigEntity;
import com.zhangc.blog.admin.entity.BlogInfoEntity;
import com.zhangc.blog.admin.entity.BlogLinkEntity;
import com.zhangc.blog.admin.entity.BlogPwdEntity;
import com.zhangc.blog.admin.entity.BlogTagEntity;
import com.zhangc.blog.admin.entity.UserEntity;
import com.zhangc.blog.admin.service.BlogCategoryServiceImpl;
import com.zhangc.blog.admin.service.BlogCommentServiceImpl;
import com.zhangc.blog.admin.service.BlogConfigServiceImpl;
import com.zhangc.blog.admin.service.BlogInfoServiceImpl;
import com.zhangc.blog.admin.service.BlogLinkServiceImpl;
import com.zhangc.blog.admin.service.BlogPwdService;
import com.zhangc.blog.admin.service.BlogTagServiceImpl;
import com.zhangc.blog.admin.service.UserService;
import com.zhangc.blog.admin.web.dto.LoginRespDto;
import com.zhangc.blog.admin.web.security.CurrentUser;
import com.zhangc.blog.admin.web.security.JwtTokenProvider;
import com.zhangc.blog.admin.web.security.UserPrincipal;
import com.zhangc.blog.base.ResultBO;
import com.zhangc.blog.base.constants.SysConfigConstants;
import com.zhangc.blog.base.enums.BlogExceptionCode;
import com.zhangc.blog.base.enums.DeleteStatusEnum;
import com.zhangc.blog.base.utils.FileUtils;
import com.zhangc.blog.base.validator.Validators;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Controller
@RequestMapping("/admin/v1")
public class BlogAdminV1Controller {
    @Autowired
    private BlogConfigServiceImpl blogConfigService;
    @Autowired
    private BlogCategoryServiceImpl blogCategoryService;
    @Autowired
    private BlogInfoServiceImpl blogInfoService;
    @Autowired
    private BlogLinkServiceImpl blogLinkService;
    @Autowired
    private BlogTagServiceImpl blogTagService;
    @Autowired
    private BlogCommentServiceImpl blogCommentService;
    @Autowired
    private BlogPwdService blogPwdService;

    //跳转登录界面
    @GetMapping(value = "/login")
    public String login() {
        return "adminLayui/login";
    }

    //返回welcome界面
    @GetMapping("/welcome")
    public String welcome() {
        return "adminLayui/welcome";
    }

    //返回welcome界面
    @GetMapping("/mypwd")
    public ModelAndView mypwd(String owner) {
        ModelAndView mv = new ModelAndView();
        List<BlogPwdEntity> list = blogPwdService.getBlogPwdList(owner);
        List<String> owners = blogPwdService.getAllBelongs();
        mv.addObject("data", list);
        mv.addObject("owners", owners);
        mv.setViewName("adminLayui/mypwd");
        return mv;
    }

    //注销登录
    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "adminLayui/login";
    }

    //返回个人信息界面
    @GetMapping("/userInfo")
    public ModelAndView gotoUserInfo(@CurrentUser UserPrincipal user) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("loginUserName", user.getUsername());
        mv.addObject("loginNickName", user.getName());
        mv.addObject("authorImg", blogConfigService.getAllConfigs().getOrDefault("sysAuthorImg", null));
        mv.setViewName("adminLayui/userInfo-edit");
        return mv;
    }

    @Autowired
    private UserService userService;
    @Autowired
    JwtTokenProvider tokenProvider;
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    PasswordEncoder passwordEncoder;

    //登录验证
    @ResponseBody
    @PostMapping(value = "/login")
    public ResultBO<?> login(String username, String password, HttpSession session) {
        if (StringUtils.isAnyBlank(username, password)) {
            Validators.throwAnyway(BlogExceptionCode.ADMIN_USERNAME_PWD_BLANK);
        }
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        username,
                        password
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = tokenProvider.generateToken(authentication);
        LoginRespDto dto = new LoginRespDto();
        dto.setToken("Bearer " + jwt);
        dto.setUrl("/admin/v1/index");
        return ResultBO.of(dto);
    }

    //验证旧的密码是否正确
    @ResponseBody
    @GetMapping("/password")
    public ResultBO<String> validatePassword(String oldPwd, @CurrentUser UserPrincipal currentUser) {
        if (!this.passwordEncoder.matches(oldPwd, currentUser.getPassword())) {
            return ResultBO.error(null);
        }
        return ResultBO.success();
    }

    //返回首页相关数据
    @GetMapping("/index")
    public String index(HttpSession session, @CurrentUser UserPrincipal user) {
        session.setAttribute("categoryCount", blogCategoryService.count(
                new QueryWrapper<BlogCategoryEntity>().lambda().eq(BlogCategoryEntity::getIsDeleted,
                        DeleteStatusEnum.NO_DELETED.getStatus())
        ));
        session.setAttribute("blogCount", blogInfoService.count(
                new QueryWrapper<BlogInfoEntity>().lambda().eq(BlogInfoEntity::getIsDeleted,
                        DeleteStatusEnum.NO_DELETED.getStatus())
        ));
        session.setAttribute("linkCount", blogLinkService.count(
                new QueryWrapper<BlogLinkEntity>().lambda().eq(BlogLinkEntity::getIsDeleted,
                        DeleteStatusEnum.NO_DELETED.getStatus())
        ));
        session.setAttribute("tagCount", blogTagService.count(
                new QueryWrapper<BlogTagEntity>().lambda().eq(BlogTagEntity::getIsDeleted,
                        DeleteStatusEnum.NO_DELETED.getStatus())
        ));
        session.setAttribute("commentCount", blogCommentService.count(
                new QueryWrapper<BlogCommentEntity>().lambda().eq(BlogCommentEntity::getIsDeleted,
                        DeleteStatusEnum.NO_DELETED.getStatus())
        ));
        session.setAttribute("sysList", blogConfigService.list());
        session.setAttribute("loginNickName", user == null ? "无名氏" : user.getName());
        return "adminLayui/index";
    }

    //修改用户信息, 成功之后清空session并跳转登录页
    @ResponseBody
    @PostMapping("/userInfo")
    public ResultBO<String> userInfoUpdate(HttpSession session, String userName, String newPwd,
            String nickName, @CurrentUser UserPrincipal currentUser) {
        if (currentUser == null || currentUser.getId() == null) {
            return ResultBO.error(null, "-1", "当前人身份信息失败");
        }
        if (StringUtils.isAnyBlank(userName, newPwd)) {
            return ResultBO.error(null, "-1", "入参错误");
        }
        UserEntity adminUser = new UserEntity();
        adminUser.setPwd(passwordEncoder.encode(newPwd));
        adminUser.setId(currentUser.getId());
        adminUser.setName(nickName);
        if (userService.updateUserInfo(adminUser)) {
            //修改成功后清空session中的数据，前端控制跳转至登录页
            return ResultBO.of("/admin/v1/logout");
        } else {
            return ResultBO.error(null, "-1", "服务器错误");
        }
    }

    @ResponseBody
    @GetMapping("/reload")
    public boolean reload(HttpSession session, @CurrentUser UserPrincipal currentUser) {
        return currentUser != null && currentUser.getId() != null && currentUser.getId() != 0;
    }

    //用户头像上传
    @PostMapping({ "/upload/authorImg" })
    @ResponseBody
    public ResultBO<String> upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws URISyntaxException {
        String suffixName = FileUtils.getSuffixName(file);
        //生成文件名称通用方法
        String newFileName = FileUtils.getNewFileName(suffixName);
        File fileDirectory = new File(FileUtils.UPLOAD_AUTHOR_IMG);
        //创建文件
        File destFile = new File(FileUtils.UPLOAD_AUTHOR_IMG + newFileName);
        try {
            if (!fileDirectory.exists()) {
                if (!fileDirectory.mkdirs()) {
                    throw new IOException("文件夹创建失败,路径为：" + fileDirectory);
                }
            }
            file.transferTo(destFile);
            String sysAuthorImg = FileUtils.SQL_AUTHOR_IMG + newFileName;
            BlogConfigEntity blogConfig = new BlogConfigEntity()
                    .setConfigField(SysConfigConstants.SYS_AUTHOR_IMG.getConfigField())
                    .setConfigValue(sysAuthorImg);
            blogConfigService.updateById(blogConfig);
            return ResultBO.success();
        } catch (IOException e) {
            e.printStackTrace();
            return ResultBO.error(null, "-1", "服务器错误");
        }
    }
}
